/*
 * ***** BEGIN LICENSE BLOCK *****
 * This file is part of "myWiWall".
 * Copyright (c) 2007-2008 CRP Henri Tudor and contributors.
 * All rights reserved.
 *
 * "myWiWall" is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 * 
 * "myWiWall" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with "myWiWall"; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ***** END LICENSE BLOCK *****
 */

/*
 * This file is responsible for parsing the manifest file and creating a JavaScript object
 */


var configParser = new ConfigParser();

function ConfigParser()
{
	this.parse = function(data)
	{
		var widget = new Object();
		var xmlDoc = data.documentElement;
		
		/* parse manifest file */

		/* widget name */
		if(this.getElements('title', null, xmlDoc)[0])
			widget['widgetname'] = this.getElements('title', null, xmlDoc)[0].childNodes[0].nodeValue;
		else
			throw 'Required element \'title\' not found in config.xml';

		/* width */
		if(xmlDoc.getAttribute('width'))
			widget['width'] = parseInt(xmlDoc.getAttribute('width'));
		else
			throw 'Required attribute \'width\' not found in config.xml';
		
		/* height */	
		if(xmlDoc.getAttribute('height'))
			widget['height'] = parseInt(xmlDoc.getAttribute('height'));
		else
			throw 'Required attribute \'height\' not found in config.xml';
		
		/* id */
		if(xmlDoc.getAttribute('id'))
			widget['id'] = xmlDoc.getAttribute('id');
		else
			throw 'Required attribute \'id\' not found in config.xml';
			
		/* scrollable */	
		if(this.getElements('scrollable', 'palette', xmlDoc)[0])
			widget['scrollable'] = this.getElements('scrollable', 'palette', xmlDoc)[0].childNodes[0].nodeValue;
	
		/* author */
		if(this.getElements('author', null, xmlDoc)[0])
		{
			var author = this.getElements('author', null, xmlDoc)[0];
			
			widget['author_name'] = author.childNodes[0].nodeValue;
			
			if (author.getAttribute('url')) {
				widget['author_url'] = author.getAttribute('url');
			}
			if (author.getAttribute('email')) {
				widget['author_email'] = author.getAttribute('email');
			}
		}
		
		/* description */
		if(this.getElements('description', null, xmlDoc)[0])
			widget['description'] = this.getElements('description', null, xmlDoc)[0].childNodes[0].nodeValue;
		
		/* icon */
		if(this.getElements('icon', null, xmlDoc)[0])
			widget['icon'] = this.getElements('icon', null, xmlDoc)[0].getAttribute('src');
	
		/* widget_type, if not defined the default is local */
		if (this.getElements('widget_type', 'palette', xmlDoc)[0])
			widget['widget_type'] = this.getElements('widget_type', 'palette', xmlDoc)[0].childNodes[0].nodeValue;
		else
			widget['widget_type'] = 'local';
		
		/* widget_location */
		if (this.getElements('widget_location', 'palette', xmlDoc)[0])
			widget['widget_location'] = this.getElements('widget_location', 'palette', xmlDoc)[0].childNodes[0].nodeValue;
		else
			if (widget['widget_type'] == 'remote')
				throw 'Required element \'widget_location\' for widget_type \'remote\' not found in config.xml';
		
		/* widget alternate URL */
		if (this.getElements('alternate_url', 'palette', xmlDoc)[0])
			widget['alternate_url'] = this.getElements('alternate_url', 'palette', xmlDoc)[0].childNodes[0].nodeValue;
		
		/* widget authentication */
		if (this.getElements('widget_authentication', 'palette', xmlDoc)[0])
			widget['widget_authentication'] = this.getElements('widget_authentication', 'palette', xmlDoc)[0].childNodes[0].nodeValue;
		else
			widget['widget_authentication'] = 'disabled';
		
		/* widget preferences */
		if (this.getElements('preferences', 'palette', xmlDoc)[0])
		{
			var preferences = this.getElements('preferences', 'palette', xmlDoc)[0].childNodes;
			
			widget['preferences'] = new Object();
			
			/* preference name regular expression */
			var re = new RegExp("^[a-zA-Z0-9_]+$");
			
			for (var i = 0; i < preferences.length; i++)
			{
				/* skip text nodes */
				if (preferences[i].nodeType == 3)
					continue;

				/* skip comment nodes */
				if (preferences[i].nodeType == 8)
					continue;					
				
				if(!preferences[i].getAttribute('name'))
				{
					throw 'Required attribute \'name\' not found in preference element.';
				}
				else if (!re.test(preferences[i].getAttribute('name')))
				{
					throw 'Attribute \'name\' must contain only letters, number and underscores.';
				}
				else if (widget['preferences'][preferences[i].getAttribute('name')])
				{
					throw 'Duplicate attribute \''+preferences[i].getAttribute('name')+'\' found.';
				}
				else
				{
					widget['preferences'][preferences[i].getAttribute('name')] = this.parsePreferences(preferences[i]);
				}
			}
		}
	
		return widget;
	}
	
	/* a method to parse the manifest preferences into an object */
	this.parsePreferences = function(p)
	{
		var pref = new Object();
		
		pref['name'] = p.getAttribute('name');
		
		if (p.getAttribute('display_name'))
			pref['display_name'] = p.getAttribute('display_name');
		else
			pref['display_name'] = p.getAttribute('name');
		
		/* default_value is needed for devEnv only */
		if (p.getAttribute('default_value'))
			pref['default_value'] = p.getAttribute('default_value');

		if (p.getAttribute('datatype'))
			pref['datatype'] = p.getAttribute('datatype');
		else
			pref['datatype'] = 'string';
			
		switch(pref['datatype'])
		{
			case 'bool':
				pref['value'] = (p.getAttribute('value') == 1) ? true : false;
				break;
			case 'number':
				pref['value'] = parseInt(p.getAttribute('value'));
				break;
			default:
				pref['value'] = p.getAttribute('value');
				break;
		}
		
		if(pref['datatype'] == 'enumeration')
		{
			var en = new Object();
			for (t = 0; t < p.childNodes.length; t++)
			{
				/* skip text nodes */
				if (p.childNodes[t].nodeType == 3)
					continue;
					
				en[p.childNodes[t].getAttribute('value')] = p.childNodes[t].getAttribute('display_value');
			}
			pref['values'] = en;
		}
		return pref;
	}
	
	/* a utility method that takes cares of the IE XML namespace bug */
	this.getElements = function(tagname, namespace, xmlDoc)
	{
		var t = xmlDoc.getElementsByTagName(tagname);
		if (t.length > 0)
			return t;
			
		if (namespace)
		{
			t = xmlDoc.getElementsByTagName(namespace+":"+tagname);
			if (t.length > 0)
				return t;
		}	
		return new Array();
	}
}
